//****************************************Copyright (c)***********************************//
//Copyright(C) 写的bug都队 2023-2033
//All rights reserved                                  
//----------------------------------------------------------------------------------------
// File name:           udp
// Last modified Date:  2023/11/9
// Last Version:        V2.0
// Descriptions:        以太网数据处理模块，实现以太网收发
//----------------------------------------------------------------------------------------
// Author :             写的bug都队
// Created date:        2023/10/22
//****************************************************************************************//

module udp(
    //system
    input                           rst_n             ,
    //RMII接口
    input                           netrmii_clk50m    ,     //RMII时钟线 phy芯片提供
    input                           netrmii_rx_crs    ,     //载波侦听信号 1:有数据接收 0:无数据接收
    input     [1:0]                 netrmii_rxd       ,     //RMII数据接收
    output                          netrmii_txen      ,     //RMII传输使能
    output    [1:0]                 netrmii_txd       ,     //RMII数据发送
    //udp发送
    input     [31:0]                udp_tx_data       ,     //以太网待发送数据
    input     [15:0]                udp_tx_byte_num   ,     //以太网发送的有效字节数 单位:byte
    input                           udp_tx_start_en   ,     //以太网开始发送信号
    output                          udp_tx_done       ,     //以太网发送完成信号
    output                          udp_tx_req        ,     //读数据请求信号
    //udp接收
    output                          rec_pkt_done      ,     //以太网单包数据接收完成信号
    output                          rec_en            ,     //以太网接收的数据使能信号
    output    [31:0]                rec_data          ,     //以太网接收的数据
    output    [15:0]                rec_byte_num            //以太网接收的有效字节数 单位:byte
);

//****************** 参数声明 *******************//
//板子MAC
parameter BOARD_MAC = {8'h06, 8'h00, 8'haa, 8'hbb, 8'h0c, 8'hdd};
//板子IP 
parameter BOARD_IP  = {8'd192,8'd168,8'd15,8'd14};

//以太网参数
reg             phy_rdy;            //phy ready

//以太网发送参数
reg   [7:0]     eth_tx_data;        //
reg             eth_tx_en;          //
wire            rmii_tx_en;         //rmii传输使能信号
wire  [7:0]     rmii_tx_data;       //需要传输的rmii数据
wire            tx_bz;              //0:表示线路空闲
wire            tx_av;              //1:数据有效
wire            tx_done;            //表明传输完成的信号
reg   [7:0]     eth_tx_status;      //发送状态

//以太网接收参数
wire            rmii_data_en;       //RMII接收数据转换后的有效信号
wire  [7:0]     rx_data_s;          //RMII接收转换后的数据


//****************** 参数定义 *******************//
assign tx_done = udp_tx_done;

//phy芯片初始化信号
always@(posedge netrmii_clk50m or negedge rst_n)begin
  if(!rst_n) 
    phy_rdy <= 1'd0;
  else   
    phy_rdy <= 1'd1;
end



//****************** 模块例化 *******************//

/****************** UDP发送 *******************/
udp_tx udp_tx_inst(
    .clk                  (netrmii_clk50m     ),           //发送时钟：50M
    .rst_n                (rst_n              ),           //复位
    .tx_start_en          (udp_tx_start_en    ),           //以太网开始发送信号
    .tx_data              (udp_tx_data        ),           //需要发送的数据（32bit）
    .tx_byte_num          (udp_tx_byte_num    ),           //以太网发送的有效字节数 单位:byte
    .tx_done              (udp_tx_done        ),           //以太网发送完成信号
    .tx_req               (udp_tx_req         ),           //读数据请求信号
    .rmii_tx_en           (rmii_tx_en         ),           //rmii发送有效
    .rmii_tx_data         (rmii_tx_data       )            //rmii发送数据
);

rmii_tx rmii_tx_inst(
    .clk                  (netrmii_clk50m     ), 
    .rst                  (phy_rdy            ),
    .data                 (eth_tx_data        ),
    .tx_en                (eth_tx_en          ),
    .tx_bz                (tx_bz              ),
    .tx_av                (tx_av              ),
    .p_txd                (netrmii_txd        ),
    .p_txen               (netrmii_txen       )
);

//传输环节：跟物理层相配合的部分
always@(posedge netrmii_clk50m or negedge rst_n)begin
  if(!rst_n) begin  
      eth_tx_status <= 0;
  end else begin
    case(eth_tx_status)
      0:begin                    //wait for phy ready and tx_trigger
          eth_tx_en <= 0;
          if(phy_rdy == 1) begin
              eth_tx_status <= 1;
          end
      end
      1:begin                    //wait for tx_bz==0  //表示线路空闲
          if(tx_bz == 1'b0) begin
              eth_tx_status <= 2;
          end
      end
      2:begin
          if(rmii_tx_en == 1) begin
              eth_tx_en <= 1;
              eth_tx_data <= rmii_tx_data;
              eth_tx_status <= 3;
          end
      end
      3:begin
          eth_tx_data <= rmii_tx_data;
          if(tx_done) begin      //结束条件
              eth_tx_status <= 4;
          end
      end
      4:begin
          eth_tx_en <= 0;
          eth_tx_status <= 0;
      end
    endcase
  end
end

/****************** UDP接收 *******************/
rmii_rx rmii_rx_inst(
    .clk50m               (netrmii_clk50m     ),
    .phy_rdy              (phy_rdy            ),
    .crs                  (netrmii_rx_crs     ),
    .rxd                  (netrmii_rxd        ),
    .rmii_data_en         (rmii_data_en       ),
    .rx_data_s            (rx_data_s          )
);

udp_rx 
#(
    .BOARD_MAC          (BOARD_MAC            ),             //板子MAC
    .BOARD_IP           (BOARD_IP             )              //板子IP
)
udp_rx_inst(
    .clk                (netrmii_clk50m       ),
    .rst_n              (rst_n                ),
    .rmii_data_en       (rmii_data_en         ),
    .rmii_data          (rx_data_s            ),
    .rec_pkt_done       (rec_pkt_done         ),             //以太网单包数据接收完成信号
    .rec_en             (rec_en               ),             //以太网接收的数据使能信号
    .rec_data           (rec_data             ),             //以太网接收的数据
    .rec_byte_num       (rec_byte_num         )              //以太网接收的有效字节数 单位:byte
); 

  


endmodule